home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1998 June / SGI Freeware 1998 June.iso / dist / fw_ATxgopher.idb / usr / freeware / src / xgopher.1.3 / save.c.z / save.c
C/C++ Source or Header  |  1998-01-21  |  35KB  |  1,409 lines

  1. /* save.c
  2.    make the file save dialog popup, and manage it. */
  3.  
  4.      /*---------------------------------------------------------------*/
  5.      /* Xgopher        version 1.3     08 April 1993                  */
  6.      /*                version 1.2     20 November 1992               */
  7.      /*                version 1.1     20 April 1992                  */
  8.      /*                version 1.0     04 March 1992                  */
  9.      /* X window system client for the University of Minnesota        */
  10.      /*                                Internet Gopher System.        */
  11.      /* Allan Tuchman, University of Illinois at Urbana-Champaign     */
  12.      /*                Computing and Communications Services Office   */
  13.      /* Copyright 1992, 1993 by                                       */
  14.      /*           the Board of Trustees of the University of Illinois */
  15.      /* Permission is granted to freely copy and redistribute this    */
  16.      /* software with the copyright notice intact.                    */
  17.      /*---------------------------------------------------------------*/
  18.  
  19. #include <stdio.h>
  20. #include <ctype.h>
  21. /* Some systems don't have isgraph() defined in ctype.h. */
  22. #ifndef isgraph
  23. #define isgraph(c) (isprint(c) && (c) != ' ')
  24. #endif
  25.  
  26. #include <X11/Intrinsic.h>
  27. #include <X11/StringDefs.h>
  28. #include <X11/Xaw/Box.h>
  29. #include <X11/Xaw/Command.h>
  30. #include <X11/Xaw/Dialog.h>
  31. #include <X11/Xaw/AsciiText.h>
  32. #include <X11/Xaw/Label.h>
  33. #include <X11/Shell.h>
  34.  
  35. #include <sys/types.h>
  36. #include <sys/stat.h>
  37.  
  38. #include "compatR4.h"
  39. #include "gopher.h"
  40. #include "osdep.h"
  41. #include "appres.h"
  42. #include "globals.h"
  43. #include "xglobals.h"
  44. #include "gui.h"
  45. #include "misc.h"
  46.  
  47.  
  48. /* 
  49.     "Save" is single-threaded by issuing a grab nonexclusive when
  50.     poped up.  So it is safe to use these globals to store an open
  51.     file descriptor and other information.  Be careful if this
  52.     ever changes.
  53. */
  54. typedef enum {SAVE_copy, SAVE_displayedText} saveType;
  55.  
  56. #define OPENFLAGS_NEWFILE    (O_CREAT | O_EXCL | O_WRONLY)
  57. #define OPENFLAGS_OVERWRITE    (O_CREAT | O_TRUNC | O_WRONLY)
  58. #define OPENFLAGS_APPEND    (O_APPEND | O_WRONLY)
  59.  
  60. static    int        FDToSave;
  61. static    int        saveLen;
  62. static    gopherItemP    giSaved;
  63. static    XtPointer    tepSaved;
  64. /*
  65. static    BOOLEAN        (*copyProc)();
  66. */
  67. static    saveType    returnTo;
  68.  
  69. void    makeCD();
  70. void    makeDupFile();
  71.  
  72.  
  73. static Widget    topLevel;
  74. static Widget    saveShell;
  75. static Widget    fileNameText, dirPath;
  76. static Widget    fileErrMessage;
  77. static Widget    saveLabel1, saveLabel2;
  78.  
  79. static char    currentDir[PATH_NAME_LEN];
  80.  
  81. #define SAVE_POPUP_NAME        "savePopup"
  82.                 /* default values */
  83. static popupPosResources    placementSave = {
  84.     /* position at the top of the main panel, centered across */
  85.     from_widget, 0, 10, justify_top_left, justify_top_left, True, True
  86.     };
  87.  
  88. #define COPY_POPUP_NAME        "copyPopup"
  89.                 /* default values */
  90. static popupPosResources    placementCopy = {
  91.     /* position at the top of the main panel, centered across */
  92.     from_main, 0, 10, justify_top_left, justify_top_left, True, True
  93.     };
  94.  
  95. typedef enum {Dup_none, Dup_overwrite, Dup_again, Dup_append, Dup_cancel}
  96.     dupType;
  97.  
  98. static dupType duplicateName = Dup_none;
  99.  
  100.  
  101. /* saveOkProc
  102.    accept file name and complete the copy-to-file or the 
  103.    save-displayed-text command */
  104.  
  105. void
  106. saveOkProc(w, client_data, call_data)
  107. Widget        w;
  108. XtPointer    client_data, call_data;
  109. {
  110.     int        c;
  111.     char        *tempFile, *newFile, *p;
  112.     int        outFD;
  113.     BOOLEAN        rc;
  114.     char        message[MESSAGE_STRING_LEN];
  115.     struct stat    buf;
  116.     Arg        args[10];
  117.     Cardinal    n = 0;
  118.     int        openFlags;
  119.  
  120.     /* clear previous warning */
  121.  
  122.     n = 0;
  123.     XtSetArg(args[n], XtNlabel, "");  n++;
  124.     XtSetValues(fileErrMessage, args, n);
  125.  
  126.     /* get the file name */
  127.  
  128.     n = 0;
  129.     XtSetArg(args[n], XtNstring, &tempFile);  n++;
  130.     XtGetValues(fileNameText, args, n);
  131.  
  132.     newFile = tildePath(tempFile);
  133.  
  134.     for (p=newFile; isgraph(*p); p++) ;
  135.     if (*p != NULLC) {
  136.         /* truncated at first non-printable character */
  137.         *p = NULLC;
  138.     } 
  139.     if (*newFile == NULLC) {
  140.         sprintf(message, "Warning: This is not a legal file name");
  141.  
  142.         n = 0;
  143.         XtSetArg(args[n], XtNlabel, message);  n++;
  144.         XtSetValues(fileErrMessage, args, n);
  145.  
  146.         return;
  147.     }
  148.  
  149.     switch (duplicateName) {
  150.     case Dup_none:            /* first time through */
  151.     case Dup_again:            /* already informed user */
  152.         if (stat(newFile, &buf) == 0) {
  153.             displayDupFile(newFile);
  154.             return;
  155.         }
  156.         openFlags = OPENFLAGS_NEWFILE;
  157.         break;
  158.     case Dup_overwrite:
  159.         openFlags = OPENFLAGS_OVERWRITE;
  160.         break;
  161.     case Dup_append:
  162.         openFlags = OPENFLAGS_APPEND;
  163.         break;
  164.     case Dup_cancel:    /* should not actually get here */
  165.         XtPopdown(saveShell);
  166.         return;
  167.         break;
  168.     }
  169.  
  170.     if ((outFD = open(newFile, openFlags,
  171.                     SAVE_FILE_MODE)) < 0) {
  172.         perror("save");
  173.         sprintf(message, "Warning: The file cannot be opened");
  174.  
  175.         n = 0;
  176.         XtSetArg(args[n], XtNlabel, message);  n++;
  177.         XtSetValues(fileErrMessage, args, n);
  178.  
  179.         return;
  180.     }
  181.  
  182.     XtPopdown(saveShell);
  183.  
  184.     if (returnTo == SAVE_displayedText) {
  185.         rc = saveDisplayedText(outFD, tepSaved);
  186.     } else {
  187.         rc = GI_copyFromNet(outFD, giSaved, (char *) NULL);
  188.     }
  189.  
  190.     close(outFD);
  191.  
  192.     if (! rc) {
  193.         unlink( newFile );
  194.     }
  195.  
  196.     return;
  197. }
  198.  
  199.  
  200. /* SaveOk
  201.    accept the OK action from a keyboard <cr> instead of the OK button.
  202.    The <cr> translation is defined elsewhere.
  203.    Capitalized name is for X action proc convention. */
  204.  
  205. void
  206. SaveOk(w, event, parms, nparms)
  207. Widget        w;
  208. XEvent        *event;
  209. String        *parms;
  210. Cardinal    *nparms;
  211. {
  212.     saveOkProc(w, NULL, NULL);
  213.     return;
  214. }
  215.  
  216.  
  217. /* saveCancelProc
  218.    reject file name and do not process the save command */
  219.  
  220. void
  221. saveCancelProc(w, client_data, call_data)
  222. Widget        w;
  223. XtPointer    client_data, call_data;
  224. {
  225.     XtPopdown(saveShell);
  226. }
  227.  
  228.  
  229. /* SaveCancel
  230.    accept the cancel action from a translation.
  231.    Capitalized name is for X action proc convention. */
  232.  
  233. void
  234. SaveCancel(w, event, parms, nparms)
  235. Widget        w;
  236. XEvent        *event;
  237. String        *parms;
  238. Cardinal    *nparms;
  239. {
  240.     saveCancelProc(w, NULL, NULL);
  241.     return;
  242. }
  243.  
  244.  
  245. /* saveCdProc
  246.    display change directory panel */
  247.  
  248. void
  249. saveCdProc(w, client_data, call_data)
  250. Widget        w;
  251. XtPointer    client_data, call_data;
  252. {
  253.     Arg        args[10];
  254.     Cardinal    n = 0;
  255.  
  256.     displayCD();
  257.  
  258.     /* clear previous warning */
  259.  
  260.     n = 0;
  261.     XtSetArg(args[n], XtNlabel, "");  n++;
  262.     XtSetValues(fileErrMessage, args, n);
  263. }
  264.  
  265.  
  266. /* SaveCd
  267.    accept the change directory action from a translation.
  268.    Capitalized name is for X action proc convention. */
  269.  
  270. void
  271. SaveCd(w, event, parms, nparms)
  272. Widget        w;
  273. XEvent        *event;
  274. String        *parms;
  275. Cardinal    *nparms;
  276. {
  277.     saveCdProc(w, NULL, NULL);
  278.     return;
  279. }
  280.  
  281.  
  282. /* saveHelpProc
  283.    display save help information */
  284.  
  285. void
  286. saveHelpProc(w, client_data, call_data)
  287. Widget        w;
  288. XtPointer    client_data, call_data;
  289. {
  290.     showHelp("save-copy help");
  291. }
  292.  
  293.  
  294. /* SaveHelp
  295.    accept the change directory action from a translation.
  296.    Capitalized name is for X action proc convention. */
  297.  
  298. void
  299. SaveHelp(w, event, parms, nparms)
  300. Widget        w;
  301. XEvent        *event;
  302. String        *parms;
  303. Cardinal    *nparms;
  304. {
  305.     saveHelpProc(w, NULL, NULL);
  306.     return;
  307. }
  308.  
  309.  
  310. /* makeSaveDialog
  311.    create popup dialog for saving files */
  312.  
  313. void
  314. makeSaveDialog(top)
  315. Widget    top;
  316. {
  317.     Widget        okButton, cancelButton, cdButton, helpButton;
  318.     Widget        saveForm, dirLabel;
  319.     Arg        args[10];
  320.     Cardinal    n = 0;
  321.     Dimension    wid;
  322.     static XtActionsRec    saveActionsTable[] = {
  323.                 { "saveok", (XtActionProc) SaveOk },
  324.                 { "saveCancel", (XtActionProc) SaveCancel }
  325.                 };
  326.  
  327.     topLevel = top;
  328.  
  329.     n = 0;
  330.     XtSetArg(args[n], XtNtitle, "Save or Copy to a File");  n++;
  331.     saveShell = XtCreatePopupShell("saveShell", 
  332.                     transientShellWidgetClass,
  333.                     topLevel, args, n);
  334.  
  335.  
  336.     n = 0;
  337.     XtSetArg(args[n], XtNlabel, "Save text to file ...");  n++;
  338.     XtSetArg(args[n], XtNvalue, "");  n++;
  339.     saveForm= XtCreateManagedWidget("saveForm", 
  340.                     formWidgetClass,
  341.                     saveShell, args, n);
  342.  
  343.     /* create save directory label */
  344.  
  345.         n=0;
  346.         XtSetArg(args[n], XtNjustify,   XtJustifyLeft);  n++;
  347.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  348.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  349.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  350.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  351.  
  352.     dirLabel = XtCreateManagedWidget("dirLabel", labelWidgetClass,
  353.                     saveForm, args, n);
  354.  
  355.     /* create current directory text */
  356.  
  357.         n=0;
  358.         XtSetArg(args[n], XtNeditType, XawtextRead);  n++;
  359.         XtSetArg(args[n], XtNstring, "");  n++;
  360.         XtSetArg(args[n], XtNfromVert,  dirLabel);  n++;
  361.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  362.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  363.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  364.         XtSetArg(args[n], XtNright,     XawChainRight);  n++;
  365.     dirPath = XtCreateManagedWidget("dirPath", asciiTextWidgetClass,
  366.                     saveForm, args, n);
  367.     setTextWidgetSize(dirPath, 50, 1);
  368.  
  369.     n=0;
  370.     XtSetArg(args[n], XtNwidth, &wid);  n++;
  371.     XtGetValues(dirPath, args, n);
  372.  
  373.  
  374.     /* create save labels */
  375.  
  376.         n=0;
  377.         XtSetArg(args[n], XtNfromVert,  dirPath);  n++;
  378.         XtSetArg(args[n], XtNwidth,    wid);  n++;
  379.         XtSetArg(args[n], XtNjustify,   XtJustifyLeft);  n++;
  380.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  381.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  382.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  383.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  384.     saveLabel1 = XtCreateManagedWidget("saveLabel1", labelWidgetClass,
  385.                     saveForm, args, n);
  386.  
  387.         n=0;
  388.         XtSetArg(args[n], XtNfromVert,  saveLabel1);  n++;
  389.         XtSetArg(args[n], XtNwidth,    wid);  n++;
  390.         XtSetArg(args[n], XtNjustify,   XtJustifyLeft);  n++;
  391.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  392.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  393.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  394.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  395.     saveLabel2 = XtCreateManagedWidget("saveLabel2", labelWidgetClass,
  396.                     saveForm, args, n);
  397.  
  398.     /* create file name text */
  399.  
  400.         n=0;
  401.         XtSetArg(args[n], XtNeditType,  XawtextEdit);  n++;
  402.         XtSetArg(args[n], XtNstring,    "");  n++;
  403.         XtSetArg(args[n], XtNwidth,     wid);  n++;
  404.         XtSetArg(args[n], XtNfromVert,  saveLabel2);  n++;
  405.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  406.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  407.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  408.         XtSetArg(args[n], XtNright,     XawChainRight);  n++;
  409.     fileNameText = XtCreateManagedWidget("fileName", asciiTextWidgetClass,
  410.                     saveForm, args, n);
  411.     XtOverrideTranslations(fileNameText, oneLineParsed);
  412.  
  413.  
  414.     /* create file name error message */
  415.  
  416.         n=0;
  417.         XtSetArg(args[n], XtNwidth,     wid);  n++;
  418.         XtSetArg(args[n], XtNfromVert,  fileNameText);  n++;
  419.         XtSetArg(args[n], XtNlabel,     "");  n++;
  420.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  421.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  422.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  423.         XtSetArg(args[n], XtNright,     XawChainRight);  n++;
  424.     fileErrMessage = XtCreateManagedWidget("fileErrMessage",
  425.                     labelWidgetClass,
  426.                     saveForm, args, n);
  427.  
  428.     /* create save ok button */
  429.  
  430.         n=0;
  431.         XtSetArg(args[n], XtNfromVert,  fileErrMessage);  n++;
  432.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  433.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  434.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  435.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  436.     okButton = XtCreateManagedWidget("ok", commandWidgetClass,
  437.                     saveForm, args, n);
  438.     XtAddCallback(okButton, XtNcallback, saveOkProc, NULL);
  439.  
  440.     /* create save cancel button */
  441.  
  442.         n=0;
  443.         XtSetArg(args[n], XtNfromVert,  fileErrMessage);  n++;
  444.         XtSetArg(args[n], XtNfromHoriz, okButton);  n++;
  445.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  446.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  447.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  448.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  449.     cancelButton = XtCreateManagedWidget("cancel", commandWidgetClass,
  450.                     saveForm, args, n);
  451.     XtAddCallback(cancelButton, XtNcallback, saveCancelProc, NULL);
  452.  
  453.     /* create save change directory button */
  454.  
  455.         n=0;
  456.         XtSetArg(args[n], XtNfromVert,  fileErrMessage);  n++;
  457.         XtSetArg(args[n], XtNfromHoriz, cancelButton);  n++;
  458.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  459.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  460.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  461.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  462.     cdButton = XtCreateManagedWidget("chdir", commandWidgetClass, 
  463.                     saveForm, args, n);
  464.         XtAddCallback(cdButton, XtNcallback, saveCdProc, NULL);
  465.  
  466.     /* create save help button */
  467.  
  468.         n=0;
  469.         XtSetArg(args[n], XtNfromVert,  fileErrMessage);  n++;
  470.         XtSetArg(args[n], XtNfromHoriz, cdButton);  n++;
  471.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  472.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  473.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  474.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  475.     helpButton = XtCreateManagedWidget("help", commandWidgetClass,
  476.                     saveForm, args, n);
  477.     XtAddCallback(helpButton, XtNcallback, saveHelpProc, NULL);
  478.  
  479.     XtAppAddActions(appcon, saveActionsTable, XtNumber(saveActionsTable));
  480.  
  481.     XtSetKeyboardFocus(saveForm, fileNameText);
  482.  
  483.         /* for ICCCM window manager protocol complience */
  484.  
  485.         XtOverrideTranslations (saveShell,
  486.             XtParseTranslationTable ("<Message>WM_PROTOCOLS: saveCancel()"));
  487.         XtRealizeWidget(saveShell);
  488.         (void) XSetWMProtocols (XtDisplay(saveShell),
  489.              XtWindow(saveShell), &wmDeleteAtom, 1);
  490.  
  491.  
  492.     /* find the popup placement for this shell */
  493.  
  494.     {
  495.     popupPosResources *resourcePlacement;
  496.  
  497.     resourcePlacement = getPopupPosResources(
  498.             SAVE_POPUP_NAME, POPUP_POS_CLASS, &placementSave);
  499.     bcopy( (char *) resourcePlacement, (char *) &placementSave,
  500.                 sizeof(popupPosResources) );
  501.  
  502.     resourcePlacement = getPopupPosResources(
  503.             COPY_POPUP_NAME, POPUP_POS_CLASS, &placementCopy);
  504.     bcopy( (char *) resourcePlacement, (char *) &placementCopy,
  505.                 sizeof(popupPosResources) );
  506.     }
  507.  
  508.  
  509.     makeCD(saveShell);
  510.     makeDupFile(saveShell);
  511.     
  512. }
  513.  
  514.  
  515. /* saveRequest
  516.    enable popup dialog for saving files */
  517.  
  518. void
  519. saveRequest(textShell, tep)
  520. Widget        textShell;
  521. XtPointer    tep;
  522. {
  523.  
  524.     Arg        args[10];
  525.     Cardinal    n = 0;
  526.     Position    x, y;
  527.     Dimension    w, h;
  528.     char        label[MESSAGE_STRING_LEN];
  529.     Widget        posFrom;
  530.     char        *dir;
  531.  
  532.     tepSaved = tep;
  533.     returnTo = SAVE_displayedText;
  534.  
  535.     duplicateName = Dup_none;
  536.  
  537.     dir = getwd(currentDir);
  538.     if (dir == (char *) NULL) {
  539.         fprintf (stderr, "Cannot determine current directory:\n%s\n",
  540.                 currentDir);
  541.         currentDir[0] = (char) NULL;
  542.     }
  543.  
  544.     n = 0;
  545.     XtSetArg(args[n], XtNstring, currentDir);  n++;
  546.     XtSetValues(dirPath, args, n);
  547.  
  548.     /* should give name of subject that is being saved */
  549.  
  550.     n = 0;
  551.     XtSetArg(args[n], XtNlabel, "");  n++;
  552.     XtSetValues(saveLabel1, args, n);
  553.  
  554.     sprintf(label, "Enter a file name to save the text to");
  555.     n = 0;
  556.     XtSetArg(args[n], XtNlabel, label);  n++;
  557.     XtSetValues(saveLabel2, args, n);
  558.  
  559.     n = 0;
  560.     XtSetArg(args[n], XtNstring, "");  n++;
  561.     XtSetValues(fileNameText, args, n);
  562.  
  563.     n = 0;
  564.     XtSetArg(args[n], XtNtransientFor, textShell);  n++;
  565.     XtSetValues(saveShell, args, n);
  566.  
  567.     if (placementSave.positionFrom == from_widget) {
  568.         posFrom = (textShell != NULL) ? textShell : topLevel;
  569.     }  else {
  570.         posFrom = topLevel;
  571.     }
  572.  
  573.     /* clear previous warning */
  574.  
  575.     n = 0;
  576.     XtSetArg(args[n], XtNlabel, "");  n++;
  577.     XtSetValues(fileErrMessage, args, n);
  578.  
  579.     positionAPopup(saveShell, posFrom, &placementSave);
  580.  
  581.     XtPopup(saveShell, XtGrabExclusive);
  582.  
  583.     if (appResources->warpCursor) {
  584.                 XWarpPointer(XtDisplay(saveShell), None,
  585.                                 XtWindow(fileNameText),
  586.                                 0, 0, 0, 0,
  587.                                 10, 5);
  588.  
  589.         }
  590.  
  591.     return;
  592. }
  593.  
  594.  
  595. /* saveNetRequest
  596.    enable popup dialog for saving file directly from a gopher server */
  597.  
  598. void
  599. saveNetRequest(gi)
  600. gopherItemP    gi;
  601. {
  602.     char    *suggestedName;
  603.     int    len = -1;
  604.  
  605.     Arg        args[10];
  606.     Cardinal    n = 0;
  607.     Position    x, y;
  608.     Dimension    w, h;
  609.     char        label[MESSAGE_STRING_LEN];
  610.     char        *dir;
  611.  
  612.     saveLen = len;
  613.     giSaved = gi;
  614.     /* copyProc = gi->sc->copyTypeProc; */
  615.     returnTo = SAVE_copy;
  616.  
  617.     duplicateName = Dup_none;
  618.  
  619.     dir = getwd(currentDir);
  620.     if (dir == (char *) NULL) {
  621.         fprintf (stderr, "Cannot determine current directory:\n%s\n",
  622.                 currentDir);
  623.         currentDir[0] = (char) NULL;
  624.     }
  625.  
  626.     n = 0;
  627.     XtSetArg(args[n], XtNstring, currentDir);  n++;
  628.     XtSetValues(dirPath, args, n);
  629.  
  630.     /* get the last component of the name.  If there is no '/' in
  631.        the path name, be suspicious and send NULL. */
  632.  
  633.     suggestedName = rindex(vStringValue(&(gi->selector)), '/');
  634.     if (suggestedName != NULL) suggestedName++;
  635.  
  636.     /* should give name of subject that is being saved */
  637.  
  638.     sprintf(label, "Enter a file name to receive contents of:");
  639.     n = 0;
  640.     XtSetArg(args[n], XtNlabel, label);  n++;
  641.     XtSetValues(saveLabel1, args, n);
  642.  
  643.     sprintf(label, "\"%s\"", USER_STRING(gi));
  644.     n = 0;
  645.     XtSetArg(args[n], XtNlabel, label);  n++;
  646.     XtSetValues(saveLabel2, args, n);
  647.  
  648.     n = 0;
  649.     if (suggestedName != NULL) {
  650.         XtSetArg(args[n], XtNstring, suggestedName);  n++;
  651.     } else {
  652.         XtSetArg(args[n], XtNstring, "");  n++;
  653.     }
  654.     XtSetValues(fileNameText, args, n);
  655.  
  656.     /* clear previous warning */
  657.  
  658.     n = 0;
  659.     XtSetArg(args[n], XtNlabel, "");  n++;
  660.     XtSetValues(fileErrMessage, args, n);
  661.  
  662.     positionAPopup(saveShell, topLevel, &placementCopy);
  663.  
  664.     XtPopup(saveShell, XtGrabExclusive);
  665.  
  666.     return;
  667. }
  668.  
  669.  
  670. void
  671. dupWrite()
  672. {
  673.     duplicateName = Dup_overwrite;
  674.     saveOkProc((Widget) NULL, (XtPointer) NULL, (XtPointer) NULL);
  675.     return;
  676. }
  677.  
  678.  
  679. void
  680. dupAppend()
  681. {
  682.     duplicateName = Dup_append;
  683.     saveOkProc((Widget) NULL, (XtPointer) NULL, (XtPointer) NULL);
  684.     return;
  685. }
  686.  
  687.  
  688. void
  689. dupChange()
  690. {
  691.     duplicateName = Dup_again;
  692.     return;
  693. }
  694.  
  695.  
  696. void
  697. dupCancel()
  698. {
  699.     duplicateName = Dup_cancel;
  700.     saveCancelProc((Widget) NULL, (XtPointer) NULL, (XtPointer) NULL);
  701.     return;
  702. }
  703.  
  704.  
  705. /* ====================================================================== */
  706. /* Change Directory popup                                                 */
  707. /* ====================================================================== */
  708.  
  709. static Widget    cdParent;
  710. static Widget    cdShell;
  711. static Widget    cdErrMessage;
  712. static Widget    cdPathName;
  713.  
  714. #define CD_POPUP_NAME        "cdPopup"
  715.                 /* default values */
  716. static popupPosResources    placementCD = {
  717.     /* position on the parent shell, centered near the left bottom */
  718.     from_widget, 0, 33, justify_top_left, justify_top_left, True, True
  719.     };
  720.  
  721.  
  722. /* cdOkProc
  723.    accept change directory command */
  724.  
  725. void
  726. cdOkProc(w, client_data, call_data)
  727. Widget        w;
  728. XtPointer    client_data, call_data;
  729. {
  730.     char        *path, *tempPath;
  731.     struct stat    buf;
  732.     char        message[MESSAGE_STRING_LEN];
  733.     Arg        args[10];
  734.     Cardinal    n = 0;
  735.  
  736.  
  737.     /* clear error text */
  738.  
  739.     n = 0;
  740.     XtSetArg(args[n], XtNlabel, "");  n++;
  741.     XtSetValues(cdErrMessage, args, n);
  742.  
  743.     /* ensure that the selected path exists and is writable */
  744.  
  745.     n = 0;
  746.     XtSetArg(args[n], XtNstring, &tempPath);  n++;
  747.     XtGetValues(cdPathName, args, n);
  748.  
  749.     path = tildePath(tempPath);
  750.  
  751.     if (stat(path, &buf) != 0) {
  752.         /* file/directory doesn't exist */
  753.  
  754.         fprintf (stderr, "%s does not exist\n", path);
  755.         sprintf (message, "This directory does not exist");
  756.  
  757.         n = 0;
  758.         XtSetArg(args[n], XtNlabel, message);  n++;
  759.         XtSetValues(cdErrMessage, args, n);
  760.  
  761.         return;
  762.     }
  763.     else if ((buf.st_mode & S_IFDIR) == 0) {
  764.         /* not directory */
  765.  
  766.         fprintf (stderr, "%s is not a directory\n", path);
  767.         sprintf (message, "This is not a directory");
  768.  
  769.         n = 0;
  770.         XtSetArg(args[n], XtNlabel, message);  n++;
  771.         XtSetValues(cdErrMessage, args, n);
  772.  
  773.         return;
  774.     }
  775.     else if (! isWriteableMode(&buf)) {
  776.         /* not writable */
  777.  
  778.         fprintf (stderr, "%s is not writeable\n", path);
  779.         sprintf (message, "You cannot write to this directory");
  780.  
  781.         n = 0;
  782.         XtSetArg(args[n], XtNlabel, message);  n++;
  783.         XtSetValues(cdErrMessage, args, n);
  784.  
  785.         return;
  786.     }
  787.  
  788.     if (chdir(path) != 0) {
  789.         perror("save");
  790.  
  791.         fprintf (stderr, "Cannot change to directory:\n%s\n",
  792.                 path);
  793.         sprintf (message, "You cannot change to this directory");
  794.  
  795.         n = 0;
  796.         XtSetArg(args[n], XtNlabel, message);  n++;
  797.         XtSetValues(cdErrMessage, args, n);
  798.  
  799.         return;
  800.     }
  801.  
  802.     XtPopdown (cdShell);
  803.  
  804.     strcpy(currentDir, path);
  805.  
  806.     n = 0;
  807.     XtSetArg(args[n], XtNstring, currentDir);  n++;
  808.     XtSetValues(dirPath, args, n);
  809.  
  810.     return;
  811. }
  812.  
  813.  
  814. /* CDOk
  815.    accept the OK action from a keyboard <cr> instead of the OK button.
  816.    The <cr> translation is defined elsewhere.
  817.    Capitalized name is for X action proc convention. */
  818.  
  819. void
  820. CDOk(w, event, parms, nparms)
  821. Widget        w;
  822. XEvent        *event;
  823. String        *parms;
  824. Cardinal    *nparms;
  825. {
  826.     cdOkProc(w, NULL, NULL);
  827.     return;
  828. }
  829.  
  830.  
  831. /* cdCancelProc
  832.    cancel change directory dialog */
  833.  
  834. void
  835. cdCancelProc(w, client_data, call_data)
  836. Widget        w;
  837. XtPointer    client_data, call_data;
  838. {
  839.     XtPopdown(cdShell);
  840. }
  841.  
  842.  
  843. /* CDCancel
  844.    accept the Cancel action from a keyboard <cr> instead of the Cancel button.
  845.    Capitalized name is for X action proc convention. */
  846.  
  847. void
  848. CDCancel(w, event, parms, nparms)
  849. Widget        w;
  850. XEvent        *event;
  851. String        *parms;
  852. Cardinal    *nparms;
  853. {
  854.     cdCancelProc(w, NULL, NULL);
  855.     return;
  856. }
  857.  
  858.  
  859. /* cdHelpProc
  860.    give help for change directory dialog */
  861.  
  862. void
  863. cdHelpProc(w, client_data, call_data)
  864. Widget        w;
  865. XtPointer    client_data, call_data;
  866. {
  867.     showHelp("change dir help");
  868. }
  869.  
  870.  
  871. /* CDHelp
  872.    accept the Help action from a keyboard <cr> instead of the Help button.
  873.    Capitalized name is for X action proc convention. */
  874.  
  875. void
  876. CDHelp(w, event, parms, nparms)
  877. Widget        w;
  878. XEvent        *event;
  879. String        *parms;
  880. Cardinal    *nparms;
  881. {
  882.     cdHelpProc(w, NULL, NULL);
  883.     return;
  884. }
  885.  
  886.  
  887. /* displayCD
  888.    pop up the change diretory panel */
  889.  
  890. displayCD()
  891. {
  892.     Arg        args[10];
  893.     Cardinal    n = 0;
  894.  
  895.     /* clear previous directory name and error text */
  896.  
  897.     n = 0;
  898.     XtSetArg(args[n], XtNstring, "");  n++;
  899.     XtSetValues(cdPathName, args, n);
  900.  
  901.     n = 0;
  902.     XtSetArg(args[n], XtNstring, "");  n++;
  903.     XtSetValues(cdErrMessage, args, n);
  904.  
  905.     positionAPopup(cdShell, cdParent, &placementCD);
  906.     
  907.     XtPopup (cdShell, XtGrabExclusive);
  908. }
  909.  
  910.  
  911. /* makeCD
  912.    create change directory dialog */
  913.  
  914. void
  915. makeCD(top)
  916. Widget    top;
  917. {
  918.     Widget        okButton, cancelButton, helpButton;
  919.     Widget        dirLabel;
  920.     Widget        cdForm;
  921.     Arg        args[10];
  922.     Cardinal    n = 0;
  923.     Dimension    wid;
  924.     static XtActionsRec    cdActionsTable[] = {
  925.                 { "cdok", (XtActionProc) CDOk },
  926.                 { "cdCancel", (XtActionProc) CDCancel },
  927.                 { "cdHelp", (XtActionProc) CDHelp },
  928.                 };
  929.  
  930.     cdParent = top;
  931.  
  932.         n = 0;
  933.         XtSetArg(args[n], XtNtitle, "Change Working Directory");  n++;
  934.         XtSetArg(args[n], XtNtransientFor, cdParent);  n++;
  935.     cdShell = XtCreatePopupShell("cdShell", transientShellWidgetClass,
  936.                     cdParent, args, n);
  937.  
  938.         n = 0;
  939.     cdForm= XtCreateManagedWidget("cdForm", formWidgetClass,
  940.                     cdShell, args, n);
  941.  
  942.     /* create cd label */
  943.  
  944.         n=0;
  945.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  946.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  947.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  948.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  949.  
  950.     dirLabel = XtCreateManagedWidget("cdLabel", labelWidgetClass,
  951.                     cdForm, args, n);
  952.  
  953.     /* create cd text */
  954.  
  955.         n=0;
  956.         XtSetArg(args[n], XtNeditType, XawtextEdit);  n++;
  957.         XtSetArg(args[n], XtNstring, "");  n++;
  958.         XtSetArg(args[n], XtNfromVert,  dirLabel);  n++;
  959.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  960.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  961.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  962.         XtSetArg(args[n], XtNright,     XawChainRight);  n++;
  963.     cdPathName = XtCreateManagedWidget("cdPathName", asciiTextWidgetClass,
  964.                     cdForm, args, n);
  965.     setTextWidgetSize(cdPathName, 50, 1);
  966.     XtOverrideTranslations(cdPathName, oneLineParsed);
  967.  
  968.     n=0;
  969.     XtSetArg(args[n], XtNwidth, &wid);  n++;
  970.     XtGetValues(dirPath, args, n);
  971.  
  972.  
  973.     /* create cd error message */
  974.  
  975.         n=0;
  976.         XtSetArg(args[n], XtNwidth,     wid);  n++;
  977.         XtSetArg(args[n], XtNfromVert,  cdPathName);  n++;
  978.         XtSetArg(args[n], XtNlabel,     " ");  n++;
  979.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  980.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  981.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  982.         XtSetArg(args[n], XtNright,     XawChainRight);  n++;
  983.     cdErrMessage = XtCreateManagedWidget("cdErrMessage", labelWidgetClass,
  984.                     cdForm, args, n);
  985.  
  986.     /* create cd ok button */
  987.  
  988.         n=0;
  989.         XtSetArg(args[n], XtNfromVert,  cdErrMessage);  n++;
  990.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  991.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  992.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  993.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  994.     okButton = XtCreateManagedWidget("ok", commandWidgetClass,
  995.                     cdForm, args, n);
  996.     XtAddCallback(okButton, XtNcallback, cdOkProc, NULL);
  997.  
  998.     /* create cd cancel button */
  999.  
  1000.         n=0;
  1001.         XtSetArg(args[n], XtNfromVert,  cdErrMessage);  n++;
  1002.         XtSetArg(args[n], XtNfromHoriz, okButton);  n++;
  1003.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  1004.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  1005.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  1006.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  1007.     cancelButton = XtCreateManagedWidget("cancel", commandWidgetClass,
  1008.                     cdForm, args, n);
  1009.     XtAddCallback(cancelButton, XtNcallback, cdCancelProc, NULL);
  1010.  
  1011.     /* create cd help button */
  1012.  
  1013.         n=0;
  1014.         XtSetArg(args[n], XtNfromVert,  cdErrMessage);  n++;
  1015.         XtSetArg(args[n], XtNfromHoriz, cancelButton);  n++;
  1016.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  1017.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  1018.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  1019.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  1020.     helpButton = XtCreateManagedWidget("help", commandWidgetClass,
  1021.                     cdForm, args, n);
  1022.     XtAddCallback(helpButton, XtNcallback, cdHelpProc, NULL);
  1023.  
  1024.  
  1025.     XtAppAddActions(appcon, cdActionsTable, XtNumber(cdActionsTable));
  1026.  
  1027.     XtSetKeyboardFocus(cdForm, cdPathName);
  1028.  
  1029.         /* for ICCCM window manager protocol complience */
  1030.  
  1031.         XtOverrideTranslations (cdShell,
  1032.             XtParseTranslationTable ("<Message>WM_PROTOCOLS: cdCancel()"));
  1033.         XtRealizeWidget(cdShell);
  1034.         (void) XSetWMProtocols (XtDisplay(cdShell),
  1035.              XtWindow(cdShell), &wmDeleteAtom, 1);
  1036.  
  1037.  
  1038.     /* find the popup placement for this shell */
  1039.  
  1040.     {
  1041.     popupPosResources *resourcePlacement;
  1042.  
  1043.     resourcePlacement = getPopupPosResources(
  1044.             CD_POPUP_NAME, POPUP_POS_CLASS, &placementCD);
  1045.     bcopy( (char *) resourcePlacement, (char *) &placementCD,
  1046.                 sizeof(popupPosResources) );
  1047.     }
  1048. }
  1049.  
  1050.  
  1051. /* ====================================================================== */
  1052. /* File exists already popup                                              */
  1053. /* ====================================================================== */
  1054.  
  1055. static Widget    dupFileParent;
  1056. static Widget    dupFileShell;
  1057. static Widget    dupFileLabelFN;
  1058.  
  1059. #define DUPFILE_POPUP_NAME        "dupFilePopup"
  1060.                 /* default values */
  1061. static popupPosResources    placementDupFile = {
  1062.     /* position on the parent shell, centered, with bottoms aligned */
  1063.     from_widget, 50, 90, justify_center, justify_bottom_right, True, True
  1064.     };
  1065.  
  1066.  
  1067. /* dupFileOkProc
  1068.    accept overwrite contents command */
  1069.  
  1070. void
  1071. dupFileOkProc(w, client_data, call_data)
  1072. Widget        w;
  1073. XtPointer    client_data, call_data;
  1074. {
  1075.     XtPopdown (dupFileShell);
  1076.  
  1077.     dupWrite();
  1078.     return;
  1079. }
  1080.  
  1081.  
  1082. /* DupFileOk
  1083.    accept the OK action from a keyboard <cr> instead of the OK button.
  1084.    The <cr> translation is defined elsewhere.
  1085.    Capitalized name is for X action proc convention. */
  1086.  
  1087. void
  1088. DupFileOk(w, event, parms, nparms)
  1089. Widget        w;
  1090. XEvent        *event;
  1091. String        *parms;
  1092. Cardinal    *nparms;
  1093. {
  1094.     dupFileOkProc(w, NULL, NULL);
  1095.     return;
  1096. }
  1097.  
  1098.  
  1099. /* dupFileAppendProc
  1100.    accept append contents command */
  1101.  
  1102. void
  1103. dupFileAppendProc(w, client_data, call_data)
  1104. Widget        w;
  1105. XtPointer    client_data, call_data;
  1106. {
  1107.     XtPopdown (dupFileShell);
  1108.  
  1109.     dupAppend();
  1110.     return;
  1111. }
  1112.  
  1113.  
  1114. /* DupFileAppend
  1115.    accept the append action from a keyboard action instead of the append button.
  1116.    Capitalized name is for X action proc convention. */
  1117.  
  1118. void
  1119. DupFileAppend(w, event, parms, nparms)
  1120. Widget        w;
  1121. XEvent        *event;
  1122. String        *parms;
  1123. Cardinal    *nparms;
  1124. {
  1125.     dupFileAppendProc(w, NULL, NULL);
  1126.     return;
  1127. }
  1128.  
  1129.  
  1130. /* dupFileChangeProc
  1131.    change this save request because duplicate file name */
  1132.  
  1133. void
  1134. dupFileChangeProc(w, client_data, call_data)
  1135. Widget        w;
  1136. XtPointer    client_data, call_data;
  1137. {
  1138.     XtPopdown(dupFileShell);
  1139.  
  1140.     dupChange();
  1141. }
  1142.  
  1143.  
  1144. /* DupFileChange
  1145.    accept the Change action from a keyboard action instead of the Change button.
  1146.    Capitalized name is for X action proc convention. */
  1147.  
  1148. void
  1149. DupFileChange(w, event, parms, nparms)
  1150. Widget        w;
  1151. XEvent        *event;
  1152. String        *parms;
  1153. Cardinal    *nparms;
  1154. {
  1155.     dupFileChangeProc(w, NULL, NULL);
  1156.     return;
  1157. }
  1158.  
  1159.  
  1160. /* dupFileCancelProc
  1161.    cancel this save request because duplicate file name */
  1162.  
  1163. void
  1164. dupFileCancelProc(w, client_data, call_data)
  1165. Widget        w;
  1166. XtPointer    client_data, call_data;
  1167. {
  1168.     XtPopdown(dupFileShell);
  1169.  
  1170.     dupCancel();
  1171. }
  1172.  
  1173.  
  1174. /* DupFileCancel
  1175.    accept the Cancel action from a keyboard action instead of the Cancel button.
  1176.    Capitalized name is for X action proc convention. */
  1177.  
  1178. void
  1179. DupFileCancel(w, event, parms, nparms)
  1180. Widget        w;
  1181. XEvent        *event;
  1182. String        *parms;
  1183. Cardinal    *nparms;
  1184. {
  1185.     dupFileCancelProc(w, NULL, NULL);
  1186.     return;
  1187. }
  1188.  
  1189.  
  1190. /* dupFileHelpProc
  1191.    give help for duplicate file name dialog */
  1192.  
  1193. void
  1194. dupFileHelpProc(w, client_data, call_data)
  1195. Widget        w;
  1196. XtPointer    client_data, call_data;
  1197. {
  1198.     showHelp("dup file help");
  1199. }
  1200.  
  1201.  
  1202. /* DupFileHelp
  1203.    accept the Help action from a keyboard action instead of the Help button.
  1204.    Capitalized name is for X action proc convention. */
  1205.  
  1206. void
  1207. DupFileHelp(w, event, parms, nparms)
  1208. Widget        w;
  1209. XEvent        *event;
  1210. String        *parms;
  1211. Cardinal    *nparms;
  1212. {
  1213.     dupFileHelpProc(w, NULL, NULL);
  1214.     return;
  1215. }
  1216.  
  1217.  
  1218. /* displayDupFile
  1219.    pop up the file already exists (duplicate file) panel */
  1220.  
  1221. displayDupFile(path)
  1222. char    *path;
  1223. {
  1224.     Arg        args[10];
  1225.     Cardinal    n = 0;
  1226.  
  1227.     n = 0;
  1228.     XtSetArg(args[n], XtNlabel, path);  n++;
  1229.     XtSetValues(dupFileLabelFN, args, n);
  1230.  
  1231.     positionAPopup(dupFileShell, dupFileParent, &placementDupFile);
  1232.     
  1233.     XtPopup (dupFileShell, XtGrabExclusive);
  1234. }
  1235.  
  1236.  
  1237. /* makeDupFile
  1238.    create duplicate file name notice dialog */
  1239.  
  1240. void
  1241. makeDupFile(top)
  1242. Widget    top;
  1243. {
  1244.     Widget        okButton, appendButton, changeButton,
  1245.             cancelButton, helpButton;
  1246.     Widget        label1, label2;
  1247.     Widget        dupFileForm;
  1248.     Arg        args[10];
  1249.     Cardinal    n = 0;
  1250.     Dimension    wid;
  1251.     static XtActionsRec    dupFileActionsTable[] = {
  1252.                 { "dupFileok", (XtActionProc) DupFileOk },
  1253.                  { "dupFileappend", (XtActionProc) DupFileAppend },
  1254.                  { "dupFileCancel", (XtActionProc) DupFileCancel },
  1255.                 { "dupFileHelp", (XtActionProc) DupFileHelp },
  1256.                 };
  1257.  
  1258.     dupFileParent = top;
  1259.  
  1260.         n = 0;
  1261.         XtSetArg(args[n], XtNtitle, "File Already Exists");  n++;
  1262.         XtSetArg(args[n], XtNtransientFor, dupFileParent);  n++;
  1263.     dupFileShell = XtCreatePopupShell("dupFileShell",
  1264.                     transientShellWidgetClass,
  1265.                     dupFileParent, args, n);
  1266.  
  1267.         n = 0;
  1268.     dupFileForm= XtCreateManagedWidget("dupFileForm", formWidgetClass,
  1269.                     dupFileShell, args, n);
  1270.  
  1271.     /* create dupFile label */
  1272.  
  1273.         n=0;
  1274.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  1275.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  1276.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  1277.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  1278.  
  1279.     label1 = XtCreateManagedWidget("label1", labelWidgetClass,
  1280.                     dupFileForm, args, n);
  1281.  
  1282.     /* create dupFile file name label */
  1283.  
  1284.         n=0;
  1285.         XtSetArg(args[n], XtNfromHoriz, label1);  n++;
  1286.         XtSetArg(args[n], XtNjustify,   XtJustifyLeft);  n++;
  1287.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  1288.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  1289.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  1290.         XtSetArg(args[n], XtNright,     XawChainRight);  n++;
  1291.  
  1292.     dupFileLabelFN = XtCreateManagedWidget("labelFile", labelWidgetClass,
  1293.                     dupFileForm, args, n);
  1294.     {
  1295.         Dimension    w, h;
  1296.  
  1297.         getTextSize(dupFileLabelFN, 40, 1, &w, &h);
  1298.         n=0;
  1299.         XtSetArg(args[n], XtNwidth, w);  n++;
  1300.         XtSetValues(dupFileLabelFN, args, n);
  1301.     }
  1302.  
  1303.     /* create dupFile label */
  1304.  
  1305.         n=0;
  1306.         XtSetArg(args[n], XtNfromVert,  label1);  n++;
  1307.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  1308.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  1309.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  1310.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  1311.  
  1312.     label2 = XtCreateManagedWidget("label2", labelWidgetClass,
  1313.                     dupFileForm, args, n);
  1314.  
  1315.  
  1316.     /* create dupFile ok button */
  1317.  
  1318.         n=0;
  1319.         XtSetArg(args[n], XtNfromVert,  label2);  n++;
  1320.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  1321.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  1322.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  1323.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  1324.     okButton = XtCreateManagedWidget("ok", commandWidgetClass,
  1325.                     dupFileForm, args, n);
  1326.     XtAddCallback(okButton, XtNcallback, dupFileOkProc, NULL);
  1327.  
  1328.  
  1329.     /* create dupFile cancel button */
  1330.  
  1331.         n=0;
  1332.         XtSetArg(args[n], XtNfromVert,  label2);  n++;
  1333.         XtSetArg(args[n], XtNfromHoriz, okButton);  n++;
  1334.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  1335.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  1336.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  1337.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  1338.     cancelButton = XtCreateManagedWidget("cancel", commandWidgetClass,
  1339.                     dupFileForm, args, n);
  1340.     XtAddCallback(cancelButton, XtNcallback, dupFileCancelProc, NULL);
  1341.  
  1342.  
  1343.     /* create dupFile append button */
  1344.  
  1345.         n=0;
  1346.         XtSetArg(args[n], XtNfromVert,  label2);  n++;
  1347.         XtSetArg(args[n], XtNfromHoriz, cancelButton);  n++;
  1348.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  1349.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  1350.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  1351.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  1352.     appendButton = XtCreateManagedWidget("append", commandWidgetClass,
  1353.                     dupFileForm, args, n);
  1354.     XtAddCallback(appendButton, XtNcallback, dupFileAppendProc, NULL);
  1355.  
  1356.     /* create dupFile change button */
  1357.  
  1358.         n=0;
  1359.         XtSetArg(args[n], XtNfromVert,  label2);  n++;
  1360.         XtSetArg(args[n], XtNfromHoriz, appendButton);  n++;
  1361.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  1362.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  1363.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  1364.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  1365.     changeButton = XtCreateManagedWidget("change", commandWidgetClass,
  1366.                     dupFileForm, args, n);
  1367.     XtAddCallback(changeButton, XtNcallback, dupFileChangeProc, NULL);
  1368.  
  1369.     /* create dupFile help button */
  1370.  
  1371.         n=0;
  1372.         XtSetArg(args[n], XtNfromVert,  label2);  n++;
  1373.         XtSetArg(args[n], XtNfromHoriz, changeButton);  n++;
  1374.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  1375.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  1376.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  1377.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  1378.     helpButton = XtCreateManagedWidget("help", commandWidgetClass,
  1379.                     dupFileForm, args, n);
  1380.     XtAddCallback(helpButton, XtNcallback, dupFileHelpProc, NULL);
  1381.  
  1382.  
  1383.     XtAppAddActions(appcon, dupFileActionsTable,
  1384.                 XtNumber(dupFileActionsTable));
  1385.  
  1386.  
  1387.         /* for ICCCM window manager protocol complience */
  1388.  
  1389.         XtOverrideTranslations (dupFileShell,
  1390.             XtParseTranslationTable (
  1391.                 "<Message>WM_PROTOCOLS: dupFileCancel()"));
  1392.         XtRealizeWidget(dupFileShell);
  1393.         (void) XSetWMProtocols (XtDisplay(dupFileShell),
  1394.              XtWindow(dupFileShell), &wmDeleteAtom, 1);
  1395.  
  1396.  
  1397.     /* find the popup placement for this shell */
  1398.  
  1399.     {
  1400.     popupPosResources *resourcePlacement;
  1401.  
  1402.     resourcePlacement = getPopupPosResources(
  1403.         DUPFILE_POPUP_NAME, POPUP_POS_CLASS, &placementDupFile);
  1404.     bcopy( (char *) resourcePlacement, (char *) &placementDupFile,
  1405.                 sizeof(popupPosResources) );
  1406.     }
  1407.  
  1408. }
  1409.